package com.dailyblue.java.spring.boot.security.filter;

import com.alibaba.fastjson.JSONArray;
import com.dailyblue.java.spring.boot.commons.util.JsonResult;
import com.dailyblue.java.spring.boot.commons.util.JwtConfig;
import com.dailyblue.java.spring.boot.commons.util.ResultCode;
import com.dailyblue.java.spring.boot.commons.util.ResultTool;
import com.dailyblue.java.spring.boot.security.bean.SecurityUsers;
import com.dailyblue.java.spring.boot.security.bean.Users;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Slf4j
public class SecurityLoginFilter extends UsernamePasswordAuthenticationFilter {


    private AuthenticationManager authenticationManager;
    private StringRedisTemplate stringRedisTemplate;

    public SecurityLoginFilter(AuthenticationManager authenticationManager, StringRedisTemplate stringRedisTemplate) {
        super(authenticationManager);
        this.authenticationManager = authenticationManager;
        this.stringRedisTemplate = stringRedisTemplate;
        // 关闭登录只允许 post
        this.setPostOnly(false);
        // 设置登陆路径，并且post请求
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/user/login", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        log.info("进入到了登陆校验过滤器....");
        String userName = request.getParameter("username");
        String password = request.getParameter("password");
        log.info("账号:{},密码:{}", userName, password);
        UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(userName, password);
        log.info("令牌信息:{}", upat);
        return authenticationManager.authenticate(upat);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        log.info("用户登陆成功");
        // 需要把信息保存到redis中并返回给前端token
        SecurityUsers securityUsers = (SecurityUsers) authResult.getPrincipal();
        Users user = securityUsers.getUsers();
        // 生成的token
        String token = JwtConfig.getJwtToken(ResultTool.success(user, user.getId() + ""));
        // 保存到redis中
        ValueOperations<String, String> value = stringRedisTemplate.opsForValue();
        value.set("token:" + user.getId(), token);
        // 返回给前端
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        JsonResult result = ResultTool.success(token);
        out.println(JSONArray.toJSONString(result));
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        log.info("用户登陆失败,异常信息是：{}",e.getMessage());
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        JsonResult result = ResultTool.fail(ResultCode.USER_CREDENTIALS_ERROR);
        out.println(JSONArray.toJSONString(result));
    }
}
